package main

import (
	"context"
	"net/http"

	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/protobuf/encoding/protojson"

	"mxshop_srvs/gateway/logger"
	"mxshop_srvs/gateway/setting"
	"mxshop_srvs/gateway/utils/consul"
	goodspb "mxshop_srvs/goods_srv/proto/gen/v1"
	inventorypb "mxshop_srvs/inventory_srv/proto/gen/v1"
	orderpb "mxshop_srvs/order_srv/proto/gen/v1"
)

func main() {
	// init config
	setting.Init()

	// init logger
	logger.Init()
	defer func(l *zap.Logger) {
		_ = l.Sync()
	}(zap.L())

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	mux := runtime.NewServeMux(runtime.WithMarshalerOption(
		runtime.MIMEWildcard, &runtime.JSONPb{
			MarshalOptions: protojson.MarshalOptions{
				UseProtoNames:  true, // 使用proto字段名代替JSON中的骆驼式名称的字段名。
				UseEnumNumbers: true, // 使用protoc枚举定义的值作为数字发送。
				// EmitUnpopulated: true, // 是否展示为空的字段
			},
			UnmarshalOptions: protojson.UnmarshalOptions{
				DiscardUnknown: true, // 未知字段将被忽略
			},
		},
	))

	serverConfig := []struct {
		name         string
		registerFunc func(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error)
	}{
		{
			name:         "goods-srv",
			registerFunc: goodspb.RegisterGoodsHandlerFromEndpoint,
		},
		{
			name:         "inventory-srv",
			registerFunc: inventorypb.RegisterInventoryHandlerFromEndpoint,
		},
		{
			name:         "order-srv",
			registerFunc: orderpb.RegisterOrderServiceHandlerFromEndpoint,
		},
	}

	cli, err := consul.NewConsul(setting.Conf.ConsulConfig.Host, setting.Conf.ConsulConfig.Port)
	if err != nil {
		zap.L().Fatal("cannot creates consul client", zap.Error(err))
	}

	for _, s := range serverConfig {
		addr, err := cli.GetAddr(s.name)
		if err != nil {
			zap.L().Fatal("cannot get addr", zap.Error(err))
		}
		err = s.registerFunc(
			ctx, mux, addr,
			[]grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())},
		)
		if err != nil {
			zap.L().Fatal("cannot register service", zap.String("name", s.name), zap.Error(err))
		}
	}

	zap.L().Info("grpc gateway started at", zap.String("addr", "0.0.0.0:8080"))
	zap.L().Fatal("cannot listen and server", zap.Error(http.ListenAndServe("0.0.0.0:8080", mux)))
}
